package CompletableFuture;

import org.junit.Test;

import java.util.concurrent.*;

/**
 * @author chaird
 * @create 2022-03-30 9:29
 */
public class App {
  public static void main(String[] args) {}




    @Test
    public void allOf () throws Exception{
        CompletableFuture<Integer> firstFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(6); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            return 1;
        });

        CompletableFuture<Integer> secondFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task2开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task2结束-----");
            return 1;
        });


        CompletableFuture<Integer> thirdFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task3开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task3结束-----");
            return 1;
        });


         CompletableFuture<Void> allFuture =  CompletableFuture.allOf(firstFuture,secondFuture,thirdFuture).whenComplete((res,erroeMsg)->{
             if(erroeMsg!=null){
                 System.out.println("error stack trace->");
                 erroeMsg.printStackTrace();
             }else{
                 System.out.println("run succ,result->"+res);
             }
        });


        System.out.println("res: " + allFuture.get());

    }

    @Test
    public void applyToEither() throws Exception{
        CompletableFuture<Integer> firstFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(6); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            return 1;
        });

        CompletableFuture<Integer> secondFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task2开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task2结束-----");
            return 1;
        });

        CompletableFuture<Integer> thirdFuture = firstFuture.applyToEither(secondFuture, (res)->{
            System.out.println("task3开始-----");
            System.out.println("res:" + res);
            System.out.println("task3结束-----");
            return res;
        });
        System.out.println("res: " + firstFuture.get());
        System.out.println("res: " + secondFuture.get());
        System.out.println("res: " + thirdFuture.get());
    }


    @Test
    public void whenComplete() throws Exception{
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            //报错
            if(false){
                throw new RuntimeException("test");
            }
            return 1;
        });

        CompletableFuture<Integer> whenCompleteFuture = intFuture.whenComplete((res,errorMsg)->{
            if(errorMsg!=null){
                System.out.println("error stack trace->");
                errorMsg.printStackTrace();
            }else{
                System.out.println("run succ,result->"+res);
            }
        });

        System.out.println("res: " + whenCompleteFuture.get());
    }


    @Test
    public void exceptionally() throws Exception{
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            //报错
            if(true){
                throw new RuntimeException("test");
            }
            return 1;
        });

        CompletableFuture<Integer> errorFuture = intFuture.exceptionally((errorMsg)->{
            System.out.println("报错啦-----");
            errorMsg.printStackTrace();
            System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
            return 2;
        });

        System.out.println(intFuture.get());
        //// errorFuture.get时，没有异常，但是依然有返回值，就是intFuture的返回值
        System.out.println(errorFuture.get());
    }

    /**
     * 无输入参数，无返回值
     * @throws Exception
     */
    @Test
    public void thenRun() throws Exception{
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            return 1;
        });
        CompletableFuture<Void> resFuture = intFuture.thenRun(()->{
            System.out.println("task2开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task2结束-----");
        });

        System.out.println(resFuture.get());
    }

    /**
     * 有输入参数，无返回值
     * @throws Exception
     */
    @Test
    public void thenAccept() throws Exception{
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            return 1;
        });
        CompletableFuture<Void> resFuture = intFuture.thenAccept(res->{
            System.out.println("task2开始-----");
            System.out.println("task2的参数：" + res);
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task2结束-----");
        });

        System.out.println(resFuture.get());
    }



    /**
     * 有输入参数，有返回值
     * @throws Exception
     */
    @Test
    public void thenApplyAsync() throws Exception{
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----" + Thread.currentThread().getName());
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----"+ Thread.currentThread().getName());
            return 1;
        });
        CompletableFuture<Integer> resFuture = intFuture.thenApplyAsync(res->{
            System.out.println("task2开始-----"+ Thread.currentThread().getName());
            System.out.println("task2的参数：" + res);
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task2结束-----"+ Thread.currentThread().getName());
            return 1;
        });

        System.out.println(resFuture.get());
    }


    /**
     * 有输入参数，有返回值
     * @throws Exception
     */
    @Test
    public void thenApply() throws Exception{
        CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("task1开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task1结束-----");
            return 1;
        });
        CompletableFuture<Integer> resFuture = intFuture.thenApply(res->{
            System.out.println("task2开始-----");
            System.out.println("task2的参数：" + res);
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("task2结束-----");
            return 1;
        });

        System.out.println(resFuture.get());
    }


    @Test
    public void runAsync() throws Exception{
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("开始-----");
            try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
            System.out.println("结束-----");
        });
        System.out.println(voidCompletableFuture.get());
    }

  @Test
  public void supplyAsync() throws Exception{
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          System.out.println("开始-----");
          try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
          System.out.println("结束-----");
          return "result : with result async task";
      });
    System.out.println(future.get());
  }

    @Test
    public void supplyAsynThreadPool() throws Exception{
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<String> future = executorService.submit(new Callable<String>() {
            @Override
            public String call() {
                System.out.println("开始-----");
                try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { }
                System.out.println("结束-----");
                return "result : with result async task";
            }
        });
        System.out.println(future.get());
    }
}
